package razor.blade;

import javafx.beans.binding.*;
import javafx.event.*;
import javafx.scene.*;
import javafx.scene.paint.*;
import javafx.stage.*;
import javafx.beans.property.*;
import javafx.beans.value.*;
import javafx.scene.image.*;
import javafx.scene.input.*;
import javafx.scene.shape.*;
import javafx.scene.text.*;
import javafx.geometry.*;
import tee.binding.*;

public class DesktopX {
    private DesktopX me;
    //private SimpleDoubleProperty x;
    private Numeric x;
    private Numeric y;
    private Numeric messageBoxWidth;
    private Numeric messageBoxHeight;
    private Numeric messageBoxX;
    private Numeric messageBoxY;
    private Numeric width;
    //private Numeric innerWidth;
    private Numeric height;
    //private Numeric innerHeight;
    private It<Color> color;
    private Task closeButtonPressed;
    private Group root;
    private Group contentGroup;
    private Group backGroup;
    private Group upGroup;
    private Stage primaryStage;
    private Rectangle fog;
    public DesktopX() {
	me = this;
	closeButtonPressed = null;
	//x = new SimpleDoubleProperty(0);
	x = new Numeric().value(0).afterChange(new Task() {
	    @Override public void doTask() {
		if (primaryStage != null) {
		    primaryStage.setX(x.value());
		}
	    }
	});
	//y = new SimpleDoubleProperty(0);
	y = new Numeric().value(0).afterChange(new Task() {
	    @Override public void doTask() {
		if (primaryStage != null) {
		    primaryStage.setY(y.value());
		}
	    }
	});
	color = new It<Color>().value(Color.web("#003366"));
	messageBoxWidth = new Numeric().value(300);
	messageBoxHeight = new Numeric().value(200);
	messageBoxX = new Numeric().value(200);
	messageBoxY = new Numeric().value(100);
	me.width = new Numeric().value(600).afterChange(new Task(){
	    @Override public void doTask() {
		if(primaryStage!=null)
		primaryStage.setWidth(me.width.value());
		//System.out.println(primaryStage);
	    }
	});
	me.height = new Numeric().value(400).afterChange(new Task(){
	    @Override public void doTask() {
		if(primaryStage!=null)
		primaryStage.setHeight(me.height.value());
		//System.out.println(primaryStage);
	    }
	});
	//innerWidth = new Numeric().value(600 - 32);
	//innerHeight = new Numeric().value(400 - 32);
	/*
	me.width.addListener(new ChangeListener<Number>() {
	    public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
		innerWidth.set(me.width.get() - 32);
		primaryStage.setWidth(me.width.get());
	    }
	});
	me.height.addListener(new ChangeListener<Number>() {
	    public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
		innerHeight.set(me.height.get() - 32);
		primaryStage.setHeight(me.height.get());
	    }
	});
*/
	/*me.x.addListener(new ChangeListener<Number>() {
	public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
	primaryStage.setX(me.x.get());
	}
	});*/
	/*me.y.addListener(new ChangeListener<Number>() {
	public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
	primaryStage.setY(me.y.get());
	}
	});*/

	root = new Group();
	backGroup = new Group();
	Rectangle bgClip = new Rectangle();
	bgClip.widthProperty().bind(new Tee<Double>(me.width.minus(32)));
	bgClip.heightProperty().bind(new Tee<Double>(me.height.minus(32)));
	bgClip.setX(16);
	bgClip.setY(16);
	backGroup.setClip(bgClip);
	contentGroup = new Group();
        contentGroup.setTranslateX(16);
        contentGroup.setTranslateY(16);
	backGroup = new Group();
	Rectangle cntClip = new Rectangle();
	cntClip.widthProperty().bind(bgClip.widthProperty());
	cntClip.heightProperty().bind(bgClip.heightProperty());
	//cntClip.setX(16);
	//cntClip.setY(16);
	contentGroup.setClip(cntClip);
	root.getChildren().add(new Plate()
		.width(me.width.minus(32))
		.height(me.height.minus(32))
		.x(16)
		.y(16)
		.color(color)
		.node());
	root.getChildren().add(backGroup);
	Rectangle tow = new Rectangle();
	tow.widthProperty().bind(bgClip.widthProperty());
	tow.heightProperty().bind(bgClip.heightProperty());
	tow.setFill(Color.web("#00000001"));
        final Tow dragger=new Tow();
	root.getChildren().add(dragger
            .content(tow)
            .x(new Numeric().value(16).afterChange(new Task(){
                    @Override public void doTask() {
                        if(primaryStage==null)return;
                        //System.out.println("x: "+dragger.x().value());
                        //if(dragger.x().value()<=16)return;
                        double dx=dragger.x().value()-16;
                        dragger.x(16);
                        me.x(me.x().value()+dx);
                        //primaryStage.setX(primaryStage.getX()+dx);
                    }
                }))
            .y(new Numeric().value(16).afterChange(new Task(){
                    @Override public void doTask() {
                        if(primaryStage==null)return;
                        //System.out.println("y: "+dragger.y().value());
                        //if(dragger.y().value()<=16)return;
                        double dy=dragger.y().value()-16;
                        dragger.y(16);
                        me.y(me.y().value()+dy);
                        //primaryStage.setY(primaryStage.getY()+dy);
                    }
                }))
            .node()
            );
	root.getChildren().add(contentGroup);
	upGroup = new Group();
	root.getChildren().add(upGroup);
	ImageView closeView = new ImageView();
	closeView.setImage(new Image(this.getClass().getResourceAsStream("steelBall28.png")));
	closeView.xProperty().bind(new Tee<Double>(width.minus(48)));
	closeView.setY(22);
	closeView.setCursor(Cursor.HAND);
	closeView.setOnMouseClicked(new EventHandler< MouseEvent>() {
	    public void handle(MouseEvent event) {
		//onClose();
		if (closeButtonPressed != null) {
		    closeButtonPressed.start();
		}
	    }
	});
	upGroup.getChildren().add(closeView);
	ImageView resizeView = new ImageView();
	resizeView.setImage(new Image(this.getClass().getResourceAsStream("steelBall28.png")));
        Tow resizeTow=new Tow();
	upGroup.getChildren().add(resizeTow
		.x(me.width.minus(48))
		.y(me.height.minus(48))
		.cursor(Cursor.NW_RESIZE)
		.content(resizeView)
		.node());
	fog = new Rectangle();
	//fog.setFill(Color.web("#ff0000"));
	fog.setX(16);
	fog.setY(16);
	fog.widthProperty().bind(new Tee<Double>(width.minus(32)));
	fog.heightProperty().bind(new Tee<Double>(height.minus(32)));
	Stop[] stops = new Stop[]{new Stop(0, Color.web("#00000033")), new Stop(1, Color.web("#00000066"))};
	RadialGradient g = new RadialGradient(0, 0, 0.5, 0.5, 0.5, true, CycleMethod.NO_CYCLE, stops);
	fog.setFill(g);
	fog.setVisible(false);
	root.getChildren().add(fog);
    }
    public DesktopX item(Node n) {
	contentGroup.getChildren().add(n);
	return this;
    }
    public Font font(int sz){
   return Font.loadFont(this.getClass().getResourceAsStream("12503.ttf"), sz);
    }
    public void warninig(String message) {
	ImageView bgView = new ImageView();
	bgView.setImage(new Image(this.getClass().getResourceAsStream("information.png")));
	bgView.setX(-50);
	//bgView.yProperty().bind(new Tee<Double>(messageBoxHeight.minus(200)));
	Rectangle bgClip = new Rectangle();
	//bgClip.widthProperty().bind(new Tee<Double>(messageBoxWidth.minus(32)));
	//bgClip.heightProperty().bind(new Tee<Double>(messageBoxHeight.minus(32)));
	bgClip.setX(16);
	bgClip.setY(16);
	bgView.setClip(bgClip);
	bgView.setOpacity(0.1);
	Font messageFont = font(14);
		//Font.loadFont(this.getClass().getResourceAsStream("12503.ttf"), 14);
	Text messageText = new Text(message);
	messageText.setTextOrigin(VPos.TOP);
	messageText.setX(32);
	messageText.setY(32);
	messageText.setFill(Color.web("#ffffffff"));
	messageText.setFont(messageFont);
	double mw=messageBoxWidth.value();
	double mh=messageBoxHeight.value();
	double mx=	messageBoxX.value();
	double my=	messageBoxY.value();
	final DialogX xx = new DialogX();
	xx
		.onClose(new Task(){
			@Override public void doTask() {
			    xx.close();
			    messageBoxWidth(xx.width());
			    messageBoxHeight(xx.height());
			    messageBoxX(xx.x());
			    messageBoxY(xx.y());
			    fog.setVisible(false);
			}
		    })
		.width(mw)
		.height(mh)
		.x(mx)
		.y(my)
		.background(bgView)
		.item(messageText)
		.color(color);
	bgView.yProperty().bind(new Tee<Double>(xx.height().minus(200)));
        bgClip.widthProperty().bind(new Tee<Double>(xx.width().minus(32)));
	bgClip.heightProperty().bind(new Tee<Double>(xx.height().minus(32)));
	fog.setVisible(true);
	xx.show(primaryStage);
    }
    public DesktopX background(Node n) {
	backGroup.getChildren().add(n);
	return this;
    }
    /*public DesktopX width(DoubleProperty nn) {
	me.width.bindBidirectional(nn);
	return this;
    }
    public DesktopX width(double nn) {
	me.width.set(nn);
	return this;
    }
    public DesktopX width(int nn) {
	me.width.set(nn);
	return this;
    }
    public SimpleDoubleProperty width() {
	return me.width;
    }
    public DesktopX width(DoubleBinding nn) {
	nn.addListener(new ChangeListener<Number>() {
	    public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
		me.width(newValue.doubleValue());
	    }
	});
	me.width(nn.get());
	return this;
    }*/
    /*public Numeric x() {
	return x;
    }
    public DesktopX x(int it) {
	x.value(it);
	return this;
    }
    public DesktopX x(It<Double> it) {
	x.bind(it);
	return this;
    }
    public Numeric y() {
	return y;
    }
    public DesktopX y(int it) {
	y.value(it);
	return this;
    }
    public DesktopX y(It<Double> it) {
	y.bind(it);
	return this;
    }*/
    /*public DesktopX x(DoubleProperty nn) {
    this.x.bindBidirectional(nn);
    return this;
    }
    public DesktopX x(double nn) {
    this.x.set(nn);
    return this;
    }
    public DesktopX x(int nn) {
    this.x.set(nn);
    return this;
    }
    public SimpleDoubleProperty x() {
    return x;
    }
    public DesktopX x(DoubleBinding nn) {
    nn.addListener(new ChangeListener<Number>() {
    public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
    x(newValue.doubleValue());
    }
    });
    x(nn.get());
    return this;
    }*/
    /*public DesktopX y(DoubleProperty nn) {
    this.y.bindBidirectional(nn);
    return this;
    }
    public DesktopX y(double nn) {
    this.y.set(nn);
    return this;
    }
    public DesktopX y(int nn) {
    this.y.set(nn);
    return this;
    }
    public SimpleDoubleProperty y() {
    return y;
    }
    public DesktopX y(DoubleBinding nn) {
    nn.addListener(new ChangeListener<Number>() {
    public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
    y(newValue.doubleValue());
    }
    });
    y(nn.get());
    return this;
    }*/
    
    
    public DesktopX x(double it) {
	x.value(it);
	return this;
    }
    public DesktopX x(int it) {
	x.value(it);
	return this;
    }
    public Numeric x() {
	return x;
    }
    public DesktopX x(It<Double> it) {
	x.bind(it);
	return this;
    }
    
    
    public DesktopX messageBoxWidth(double it) {
	messageBoxWidth.value(it);
	return this;
    }
    public DesktopX messageBoxWidth(int it) {
	messageBoxWidth.value(it);
	return this;
    }
    public Numeric messageBoxWidth() {
	return messageBoxWidth;
    }
    public DesktopX messageBoxWidth(It<Double> it) {
	messageBoxWidth.bind(it);
	return this;
    }
    
    
    
     public DesktopX messageBoxHeight(double it) {
	messageBoxHeight.value(it);
	return this;
    }
    public DesktopX messageBoxHeight(int it) {
	messageBoxHeight.value(it);
	return this;
    }
    public Numeric messageBoxHeight() {
	return messageBoxHeight;
    }
    public DesktopX messageBoxHeight(It<Double> it) {
	messageBoxHeight.bind(it);
	return this;
    }
    
    public DesktopX messageBoxX(double it) {
	messageBoxX.value(it);
	return this;
    }
    public DesktopX messageBoxX(int it) {
	messageBoxX.value(it);
	return this;
    }
    public Numeric messageBoxX() {
	return messageBoxX;
    }
    public DesktopX messageBoxX(It<Double> it) {
	messageBoxX.bind(it);
	return this;
    }
    
     public DesktopX messageBoxY(double it) {
	messageBoxY.value(it);
	return this;
    }
    public DesktopX messageBoxY(int it) {
	messageBoxY.value(it);
	return this;
    }
    public Numeric messageBoxY() {
	return messageBoxY;
    }
    public DesktopX messageBoxY(It<Double> it) {
	messageBoxY.bind(it);
	return this;
    }
    
    
    public DesktopX y(double it) {
	y.value(it);
	return this;
    }
    public DesktopX y(int it) {
	y.value(it);
	return this;
    }
    public Numeric y() {
	return y;
    }
    public DesktopX y(It<Double> it) {
	y.bind(it);
	return this;
    }
    public DesktopX width(double it) {
	width.value(it);
	return this;
    }
    public DesktopX width(int it) {
	width.value(it);
	return this;
    }
    public Numeric width() {
	return width;
    }
    public DesktopX width(It<Double> it) {
	width.bind(it);
	return this;
    }
    public DesktopX height(double it) {
	height.value(it);
	return this;
    }
    public DesktopX height(int it) {
	height.value(it);
	return this;
    }
    public Numeric height() {
	return height;
    }
    public DesktopX height(It<Double> it) {
	height.bind(it);
	return this;
    }
    
    
    
    
    
    /*
    public DesktopX height(DoubleProperty nn) {
	me.height.bindBidirectional(nn);
	return this;
    }
    public DesktopX height(double nn) {
	me.height.set(nn);
	return this;
    }
    public DesktopX height(int nn) {
	me.height.set(nn);
	return this;
    }
    public DesktopX height(DoubleBinding nn) {
	nn.addListener(new ChangeListener<Number>() {
	    public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
		height(newValue.doubleValue());
	    }
	});
	height(nn.get());
	return this;
    }
    public SimpleDoubleProperty height() {
	return me.height;
    }*/
    /*public DesktopX messageBoxWidth(DoubleProperty nn) {
	me.messageBoxWidth.bindBidirectional(nn);
	return this;
    }
    public DesktopX messageBoxWidth(double nn) {
	me.messageBoxWidth.set(nn);
	return this;
    }
    public DesktopX messageBoxWidth(int nn) {
	me.messageBoxWidth.set(nn);
	return this;
    }
    public DesktopX messageBoxWidth(DoubleBinding nn) {
	nn.addListener(new ChangeListener<Number>() {
	    public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
		messageBoxWidth(newValue.doubleValue());
	    }
	});
	messageBoxWidth(nn.get());
	return this;
    }
    public SimpleDoubleProperty messageBoxWidth() {
	return me.messageBoxWidth;
    }
    public DesktopX messageBoxHeight(DoubleProperty nn) {
	me.messageBoxHeight.bindBidirectional(nn);
	return this;
    }
    public DesktopX messageBoxHeight(double nn) {
	me.messageBoxHeight.set(nn);
	return this;
    }
    public DesktopX messageBoxHeight(int nn) {
	me.messageBoxHeight.set(nn);
	return this;
    }
    public DesktopX messageBoxHeight(DoubleBinding nn) {
	nn.addListener(new ChangeListener<Number>() {
	    public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
		messageBoxHeight(newValue.doubleValue());
	    }
	});
	messageBoxHeight(nn.get());
	return this;
    }
    public SimpleDoubleProperty messageBoxHeight() {
	return me.messageBoxWidth;
    }
    public DesktopX messageBoxX(DoubleProperty nn) {
	me.messageBoxX.bindBidirectional(nn);
	return this;
    }
    public DesktopX messageBoxX(double nn) {
	me.messageBoxX.set(nn);
	return this;
    }
    public DesktopX messageBoxX(int nn) {
	me.messageBoxX.set(nn);
	return this;
    }
    public DesktopX messageBoxX(DoubleBinding nn) {
	nn.addListener(new ChangeListener<Number>() {
	    public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
		messageBoxX(newValue.doubleValue());
	    }
	});
	messageBoxX(nn.get());
	return this;
    }
    public SimpleDoubleProperty messageBoxX() {
	return me.messageBoxX;
    }
    public DesktopX messageBoxY(DoubleProperty nn) {
	me.messageBoxY.bindBidirectional(nn);
	return this;
    }
    public DesktopX messageBoxY(double nn) {
	me.messageBoxY.set(nn);
	return this;
    }
    public DesktopX messageBoxY(int nn) {
	me.messageBoxY.set(nn);
	return this;
    }
    public DesktopX v(DoubleBinding nn) {
	nn.addListener(new ChangeListener<Number>() {
	    public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
		messageBoxY(newValue.doubleValue());
	    }
	});
	messageBoxY(nn.get());
	return this;
    }
    public SimpleDoubleProperty messageBoxY() {
	return me.messageBoxY;
    }*/
    public DesktopX closeButtonPressed(Task it) {
	closeButtonPressed = it;
	return this;
    }
    public DesktopX color(Color it) {
	color.value(it);
	return this;
    }
    public DesktopX color(It<Color> it) {
	color.bind(it);
	return this;
    }
    public DesktopX startup(Stage s) {
	primaryStage = s;
	primaryStage.initStyle(StageStyle.TRANSPARENT);
	/*primaryStage.xProperty().bindBidirectional(me.x);
	primaryStage.yProperty().bindBidirectional(me.y);
	primaryStage.widthProperty().bindBidirectional(me.width);
	primaryStage.heightProperty().bindBidirectional(me.height);*/
	primaryStage.setWidth(width.value());
	primaryStage.setHeight(height.value());
	primaryStage.setX(x.value());
	primaryStage.setY(y.value());
	Scene scene = new Scene(root, Color.web("#00000000"));
	primaryStage.setScene(scene);
	primaryStage.show();
	return this;
    }
}
